package com.wwu.develop.generator;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @Description 类描述：MyBatis-Plus代码生成器
 * @Author 一蓑烟雨
 * @CreateTime 2021.10.13
 * @Version 1.0.0
 **/
public class GeneratorCode {

    /**
     *  读取控制台内容
     * 也可通过以下代码获取用相应的配置文件mybatis-plus.properties中的属性
     * final ResourceBundle rb = ResourceBundle.getBundle("mybatis-plus");
     * rb.getString(“driver”)
     * @author 一蓑烟雨
     * @date 2021/10/26 0026 上午 10:21
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + "：");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            System.out.println("==========="+ipt);
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "！");
    }

    /**
     *  执行main方法控制台输入模块表名回车自动生成对应项目目录中
     * @author 一蓑烟雨
     * @date 2021/10/26 0026 上午 10:21
     */
    public static void main(String[] args) {
        // 执行
        new AutoGenerator()
                // 1.全局策略配置
                .setGlobalConfig(globalConfig())
                // 2.数据源配置
                .setDataSource(dataSourceConfig())
                // 3.数据库表策略配置
                .setStrategy(strategyConfig())
                // 4.包名配置
                .setPackageInfo(packageConfig())
                // 5.模板配置（使用自定义模板时需要将默认配置的模板设置为空）
                .setTemplate(templateConfig())
                // 6.自定义模板配置
                .setCfg(injectionConfig())
                // 设置使用的模板引擎
                .setTemplateEngine(new FreemarkerTemplateEngine())
                .execute();
    }

    /**
     *  1.全局策略配置
     * @author 一蓑烟雨
     * @date 2021/10/26 0026 上午 10:23
     */
    private static GlobalConfig globalConfig() {
        // 生成文件的输出目录
        String projectPath = System.getProperty("user.dir");
        return new GlobalConfig()
                // 作者
                .setAuthor("一蓑烟雨")
                // 是否覆盖已有文件(默认false)
                .setFileOverride(true)
                // 是否打开输出目录(默认true)
                .setOpen(false)
                // mapper.xml开启查询映射结果BaseResultMap
                .setBaseResultMap(true)
                // mapper.xml开启生成查询结果列BaseColumnList
                .setBaseColumnList(true)
                // 开启实体属性Swagger2注解(默认false)
                .setSwagger2(true);
    }


    /**
     *  2.数据源配置
     * @author 一蓑烟雨
     * @date 2021/10/26 0026 上午 10:26
     */
    private static DataSourceConfig dataSourceConfig() {
        return new DataSourceConfig()
                // 驱动连接的URL
                .setUrl("jdbc:mysql://127.0.0.1:3306/yuchen?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai")
                // 驱动名称
                .setDriverName("com.mysql.cj.jdbc.Driver")
                // 数据库连接用户名
                .setUsername("root")
                // 数据库连接密码
                .setPassword("123456");
                // 数据库类型和java类型转换
//                .setTypeConvert(new SQLTypeConvert());
    }

    /**
     *  3.数据库表策略配置
     * @author 一蓑烟雨
     * @date 2021/10/26 0026 上午 10:31
     */
    private static StrategyConfig strategyConfig() {
        //定义自动填充值的字段（比如：create_time和modify_time）
        List<TableFill>  fillList =  new ArrayList<>();
        fillList.add(new TableFill("create_time", FieldFill.INSERT));
        fillList.add(new TableFill("modifiy_time", FieldFill.INSERT_UPDATE));

        return new StrategyConfig()
                // 数据库表映射到实体的命名策略（下划线连转驼峰）
                .setNaming(NamingStrategy.underline_to_camel)
                // 数据库表字段映射到实体的命名策略（下划线连转驼峰）
                .setColumnNaming(NamingStrategy.underline_to_camel)
                // 生成不加前缀名的实体类
                .setTablePrefix("")
                // 生成的实体类启用Lombok注解(默认false)
                .setEntityLombokModel(true)
                // 生成的Controller类启用RestController注解(默认false)
                .setRestControllerStyle(true)
                .setInclude(scanner("数据库表名(多个英文逗号分割)").split(","))
                // 驼峰转连字符
                .setControllerMappingHyphenStyle(false)
                // 生成实体时是否生成字段注解(默认false)
                .setEntityTableFieldAnnotationEnable(true)
                // 插入数据或更新数据时自动填充create_time和modify_time值
                .setTableFillList(fillList);
//                // 设置实体类继承的父类
//                .setSuperEntityClass("com.wwu.common.web.BaseEntity")
//                // 实体类继承的父类的字段
//                .setSuperEntityColumns("creator","create_id","create_time")
//                // 设置Controller类继承的父类
//                .setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
    }

    /**
     *  4.包名配置
     * @author 一蓑烟雨
     * @date 2021/10/26 0026 上午 10:28
     */
    private static PackageConfig packageConfig() {
        return new PackageConfig()
                // 父包名
                .setParent("com.wwu.generator")
                .setEntity("entity")
                .setMapper("mapper")
                .setService("service")
                .setServiceImpl("service.impl")
                .setController("controller");
    }
    /**
     *  5.模板配置（使用自定义模板时需要将默认配置的模板设置为空）
     * 若使用默认配置的话，只需要将xml设置为null。并在自定义配置中设置生成路径
     * @author 一蓑烟雨
     * @date 2021/10/26 0026 上午 10:37
     */
    private static TemplateConfig templateConfig() {
        return new TemplateConfig()
                // Entity实体类
                .setEntity(null)
                // Controller前端控制器
                .setController(null)
                // mapper.xml
                .setXml(null)
                // mapper接口
                .setMapper(null)
                // Service服务类
                .setService(null)
                // ServiceImpl服务实现类
                .setServiceImpl(null);
    }

    /**
     *   6.自定义配置，主要配置模板
     * @author 一蓑烟雨
     * @date 2021/10/26 0026 上午 11:02
     */
    private static InjectionConfig injectionConfig() {
        return new InjectionConfig() {
            @Override
            public void initMap() { }
        }
        .setFileOutConfigList(fileOutConfigList());
    }

    /**
     *  自定义模板配置
     * @author 一蓑烟雨
     * @date 2021/10/26 0026 上午 10:40
     */
    private static List<FileOutConfig> fileOutConfigList() {
        //输出文件集合
        List<FileOutConfig> list = new ArrayList<>();
        //当前项目路径
        final String projectPath = System.getProperty("user.dir");
        //定义.java和mapper.xml输出文件路径
        String javaFileOutPutPath = "/yuchen-develop/src/test/java/com/wwu/generator/";
        String xmlFileOutPutPath = "/yuchen-develop/src/test/resources/";

        // 1.Entity实体类文件输出
        String entityTemplatePath = "templates/generator/entity.java.ftl";
        String entityOutPutPath = javaFileOutPutPath+"entity/";
        list.add(new FileOutConfig(entityTemplatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + entityOutPutPath + tableInfo.getEntityName() + StringPool.DOT_JAVA;
            }
        });

        // 2.Controller前端控制器文件输出
        String controllerTemplatePath = "templates/generator/controller.java.ftl";
        String controllerOutPutPath = javaFileOutPutPath+"controller/";
        list.add(new FileOutConfig(controllerTemplatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + controllerOutPutPath + tableInfo.getControllerName() + StringPool.DOT_JAVA;
            }
        });

        // 3.mapper.xml文件输出
        String mapperXmlTemplatePath = "templates/generator/mapper.xml.ftl";
        String mapperXmlOutPutPath = xmlFileOutPutPath+"mapper/";
        list.add(new FileOutConfig(mapperXmlTemplatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + mapperXmlOutPutPath + tableInfo.getMapperName() + StringPool.DOT_XML;
            }
        });

        // 4.mapper接口文件输出
        String mapperTemplatePath = "templates/generator/mapper.java.ftl";
        String mapperOutPutPath = javaFileOutPutPath+"mapper/";
        list.add(new FileOutConfig(mapperTemplatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + mapperOutPutPath + tableInfo.getMapperName() + StringPool.DOT_JAVA;
            }
        });

        // 5.server服务类文件输出
        String serviceTemplatePath = "templates/generator/service.java.ftl";
        String serviceOutPutPath = javaFileOutPutPath+"service/";
        list.add(new FileOutConfig(serviceTemplatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + serviceOutPutPath + tableInfo.getServiceName() + StringPool.DOT_JAVA;
            }
        });

        // 6.server服务实现类文件输出
        String serviceImplTemplatePath = "templates/generator/serviceImpl.java.ftl";
        String serviceImplOutPutPath = javaFileOutPutPath+"service/impl/";
        list.add(new FileOutConfig(serviceImplTemplatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + serviceImplOutPutPath + tableInfo.getServiceImplName() + StringPool.DOT_JAVA;
            }
        });

        return list;
    }
}
